package pw.yumc.Residence.gui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import com.bekvon.bukkit.residence.Residence;
import com.bekvon.bukkit.residence.protection.ClaimedResidence;

public class SetFlag {
    private final ClaimedResidence residence;
    private final Player player;
    private String targetPlayer = null;
    private Inventory inventory;
    private final LinkedHashMap<String, Integer> permMap = new LinkedHashMap<>();
    private boolean admin = false;
    private int page = 1;
    private int pageCount = 1;
    final ItemStack prev, next;

    public SetFlag(final ClaimedResidence residence, final Player player, final boolean admin) {
        this.residence = residence;
        this.player = player;
        this.admin = admin;
        prev = new ItemStack(Material.ARROW);
        final ItemMeta pmeta = prev.getItemMeta();
        pmeta.setDisplayName(FlagUtil.getConfig().getMessage("GUI.PrevInfoPage"));
        prev.setItemMeta(pmeta);
        next = new ItemStack(Material.ARROW);
        final ItemMeta nmeta = next.getItemMeta();
        nmeta.setDisplayName(FlagUtil.getConfig().getMessage("GUI.NextInfoPage"));
        next.setItemMeta(nmeta);
    }

    public List<String> getFlagLore(final Entry<String, Integer> one) {
        final List<String> lore = new ArrayList<>();
        if (FlagUtil.description.containsKey(one.getKey())) {
            lore.addAll(FlagUtil.description.get(one.getKey()));
        }
        switch (one.getValue()) {
        case 0:
            lore.add(ChatColor.GOLD + "权限状态: " + ChatColor.RED + "关闭");
            break;
        case 1:
            lore.add(ChatColor.GOLD + "权限状态: " + ChatColor.GREEN + "开启");
            break;
        case 2:
            lore.add(ChatColor.GOLD + "权限状态: " + ChatColor.DARK_RED + "未配置");
        }
        lore.addAll(FlagUtil.getConfig().getMessageList("GUI.Actions"));
        return lore;
    }

    public Inventory getInventory() {
        return this.inventory;
    }

    public Player getPlayer() {
        return this.player;
    }

    public ClaimedResidence getResidence() {
        return this.residence;
    }

    public ItemStack getStatuItem(final Entry<String, Integer> one) {
        switch (one.getValue()) {
        case 0:
            return Residence.getFlagUtilManager().getGuiFalse();
        case 1:
            return Residence.getFlagUtilManager().getGuiTrue();
        case 2:
        default:
            return Residence.getFlagUtilManager().getGuiRemove();
        }
    }

    public boolean isAdmin() {
        return this.admin;
    }

    public void recalculateInv(final Player player) {
        if (this.targetPlayer == null) {
            recalculateResidence(residence);
        } else {
            recalculatePlayer(residence);
        }
        if (player.getOpenInventory() != null) {
            player.getOpenInventory().getTopInventory().setContents(this.inventory.getContents());
        }
    }

    public void recalculatePlayer(final ClaimedResidence res) {
        Map<String, Boolean> globalFlags = Residence.getPermissionManager().getAllFlags().getFlags();
        final List<String> flags = res.getPermissions().getPosibleFlags(false, this.admin);
        final Map<String, Boolean> resFlags = new HashMap<>();
        for (final Entry<String, Boolean> one : res.getPermissions().getFlags().entrySet()) {
            if (flags.contains(one.getKey())) {
                resFlags.put(one.getKey(), one.getValue());
            }
        }
        Map<String, Boolean> pFlags;
        if (this.targetPlayer != null) {
            final ArrayList<String> PosibleResPFlags = res.getPermissions().getposibleFlags();
            final Map<String, Boolean> temp = new HashMap<>();
            for (final String one : PosibleResPFlags) {
                if (globalFlags.containsKey(one)) {
                    temp.put(one, globalFlags.get(one));
                }
            }
            globalFlags = temp;
            pFlags = res.getPermissions().getPlayerFlags(this.targetPlayer);
            if (pFlags != null) {
                for (final Entry<String, Boolean> one : pFlags.entrySet()) {
                    resFlags.put(one.getKey(), one.getValue());
                }
            }
        }
        String title = String.format(FlagUtil.getConfig().getMessage("GUI.Pset.Title"), this.targetPlayer, res.getName());
        recalculate(title, globalFlags, resFlags, res.getPermissions().getFlags(), flags);
    }

    public void recalculate(String title, Map<String, Boolean> globalFlags, Map<String, Boolean> resFlags, Map<String, Boolean> resPerm, List<String> flags) {
        final LinkedHashMap<String, Integer> TempPermMap = new LinkedHashMap<>();
        for (final Entry<String, Boolean> one : resPerm.entrySet()) {
            if (flags.contains(one.getKey())) {
                resFlags.put(one.getKey(), one.getValue());
            }
        }
        for (final Entry<String, Boolean> one : globalFlags.entrySet()) {
            if (flags.contains(one.getKey())) {
                if (resFlags.containsKey(one.getKey())) {
                    TempPermMap.put(one.getKey(), resFlags.get(one.getKey()) ? 1 : 0);
                } else {
                    TempPermMap.put(one.getKey(), 2);
                }
            }
        }
        if (title.length() > 32) {
            title = title.substring(0, Math.min(title.length(), 32));
        }
        final Inventory GuiInv = Bukkit.createInventory(new GuiHolder(this), 54, title);
        final FlagData flagData = Residence.getFlagUtilManager().getFlagData();
        this.pageCount = ((int) Math.ceil(TempPermMap.size() / 45.0D));
        final int start = this.page * 45 - 45;
        final int end = this.page * 45;
        int count = -1;
        this.permMap.clear();
        for (final Entry<String, Integer> one : TempPermMap.entrySet()) {
            count++;
            if (count >= end) {
                break;
            }
            if (count >= start) {
                this.permMap.put(one.getKey(), one.getValue());
            }
        }
        int i = 0;
        for (final Entry<String, Integer> one : this.permMap.entrySet()) {
            ItemStack MiscInfo = getStatuItem(one);
            if (flagData.contains(one.getKey())) {
                MiscInfo = flagData.getItem(one.getKey());
            }
            if (one.getValue() == 1) {
                final ItemMeta im = MiscInfo.getItemMeta();
                im.addEnchant(Enchantment.LUCK, 1, true);
                MiscInfo.setItemMeta(im);
            } else {
                MiscInfo.removeEnchantment(Enchantment.LUCK);
            }
            final ItemMeta MiscInfoMeta = MiscInfo.getItemMeta();
            MiscInfoMeta.setDisplayName(ChatColor.GREEN + one.getKey());
            MiscInfoMeta.setLore(getFlagLore(one));
            MiscInfo.setItemMeta(MiscInfoMeta);
            GuiInv.setItem(i, MiscInfo);
            i++;
            if (i > 53) {
                break;
            }
        }
        setPageItem(GuiInv);
    }

    public void recalculateResidence(final ClaimedResidence res) {
        final List<String> flags = res.getPermissions().getPosibleFlags(true, this.admin);
        final Map<String, Boolean> globalFlags = Residence.getPermissionManager().getAllFlags().getFlags();
        final Map<String, Boolean> resFlags = new HashMap<>();
        final LinkedHashMap<String, Integer> TempPermMap = new LinkedHashMap<>();
        String title = String.format(FlagUtil.getConfig().getMessage("GUI.Set.Title"), res.getName());
        recalculate(title, globalFlags, resFlags, res.getPermissions().getFlags(), flags);
    }

    public void setAdmin(final boolean state) {
        this.admin = state;
    }

    public void setPageItem(final Inventory GuiInv) {
        if (this.page > 1) {
            GuiInv.setItem(45, prev);
        }
        if (this.page < this.pageCount) {
            GuiInv.setItem(53, next);
        }
        this.inventory = GuiInv;
    }

    public void setTargePlayer(final String player) {
        this.targetPlayer = player;
    }

    public void toggleFlag(final InventoryClickEvent event) {
        final Player p = (Player) event.getWhoClicked();
        final int slot = event.getSlot();
        final ClickType click = event.getClick();
        final InventoryAction action = event.getAction();
        final ItemStack item = this.inventory.getItem(slot);
        if (item == null) { return; }
        if (slot == 53) {
            if (this.page < this.pageCount) {
                this.page += 1;
            }
            recalculateInv(p);
            return;
        }
        if (slot == 45) {
            if (this.page > 1) {
                this.page -= 1;
            }
            recalculateInv(p);
            return;
        }
        String command = "true";
        if ((click.isLeftClick()) && (action != InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
            command = "true";
        } else if ((click.isRightClick()) && (action != InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
            command = "false";
        } else if ((click.isLeftClick()) && (action == InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
            command = "remove";
        } else if ((click.isRightClick()) && (action == InventoryAction.MOVE_TO_OTHER_INVENTORY)) { return; }
        int i = 0;
        for (final Entry<String, Integer> one : this.permMap.entrySet()) {
            String flag = one.getKey();
            if (i == slot) {
                if (this.targetPlayer == null) {
                    if (this.admin) {
                        Bukkit.dispatchCommand(this.player, "resadmin set " + this.residence.getName() + " " + flag + " " + command);
                    } else {
                        Bukkit.dispatchCommand(this.player, "res set " + this.residence.getName() + " " + flag + " " + command);
                    }
                } else if (this.admin) {
                    Bukkit.dispatchCommand(this.player, "resadmin pset " + this.residence.getName() + " " + this.targetPlayer + " " + flag + " " + command);
                } else {
                    Bukkit.dispatchCommand(this.player, "res pset " + this.residence.getName() + " " + this.targetPlayer + " " + flag + " " + command);
                }
                recalculateInv(p);
                return;
            }
            i++;
        }
    }
}
